package com.travel.rabbit.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.travel.rabbit.constants.Constants;
import com.travel.rabbit.dao.UserCouponMapper;
import com.travel.rabbit.dao.UserInfoMapper;
import com.travel.rabbit.dao.UserInfoPersonalAssetsMapper;
import com.travel.rabbit.dao.UserSettingsMapper;
import com.travel.rabbit.dto.SignOutUserDTO;
import com.travel.rabbit.dto.UpdateUserDTO;
import com.travel.rabbit.dto.UserDetailsDTO;
import com.travel.rabbit.dto.UserLoginDTO;
import com.travel.rabbit.dto.UserRegisterDTO;
import com.travel.rabbit.entity.UserCoupon;
import com.travel.rabbit.entity.UserInfo;
import com.travel.rabbit.entity.UserInfoPersonalAssets;
import com.travel.rabbit.entity.UserSettings;
import com.travel.rabbit.enums.ChannelDrainageEnum;
import com.travel.rabbit.enums.DeleteEnum;
import com.travel.rabbit.enums.LoginTypeEnum;
import com.travel.rabbit.enums.RegisterTypeEnum;
import com.travel.rabbit.enums.UniqueCodeEnum;
import com.travel.rabbit.enums.UserStatusEnum;
import com.travel.rabbit.service.UserInfoService;
import com.travel.rabbit.utils.IdCardUtil;
import com.travel.rabbit.utils.StringCustomizedUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 云澜
 * @date 2023/6/16 5:04 下午
 */
@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Resource
    UserInfoMapper userInfoDao;
    @Resource
    UserCouponMapper userCouponMapper;
    @Resource
    UserSettingsMapper userSettingsMapper;
    @Resource
    IdCardUtil idCardUtil;

    @Resource
    UserInfoPersonalAssetsMapper userInfoPersonalAssetsMapper;

    @Override
    public String register(UserRegisterDTO userRegister) {
        String result;
        if (RegisterTypeEnum.MOBILE.getCode().equals(userRegister.getRegisterType())) {
            result = mobileRegister(userRegister);
        } else {
            result = nickNameRegister(userRegister);
        }
        return result;
    }

    @Override
    public String signOutUser(SignOutUserDTO signOutUserDTO) {
        UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
                .eq(UserInfo::getUserCode, signOutUserDTO.getUserCode())
                .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
        if (Objects.isNull(userInfo)){
            return Constants.user_not_exist;
        }
        UserInfoPersonalAssets personalAssets = userInfoPersonalAssetsMapper.selectOne(Wrappers.<UserInfoPersonalAssets>lambdaQuery().eq(UserInfoPersonalAssets::getUserCode, signOutUserDTO.getUserCode()));
        if (Objects.isNull(personalAssets)){
           return Constants.success;
        }

        if (personalAssets.getAccountBalance().compareTo(BigDecimal.ZERO) == 1){
          return Constants.account_balance_is_not_zero;
        }else if(personalAssets.getAccountBalance().compareTo(BigDecimal.ZERO) == 0){
            userInfo.setUserStatus(UserStatusEnum.CANCEL.getCode());
            userInfo.setIsDelete(DeleteEnum.DELETE.getCode());
            userInfo.setUpdateTime(LocalDateTime.now());
            userInfo.setUpdateBy(userInfo.getUserCode());
            userInfoDao.updateById(userInfo);

            List<UserCoupon> userCoupons = userCouponMapper.selectList(Wrappers.<UserCoupon>lambdaQuery().eq(UserCoupon::getUserId, userInfo.getId()).eq(UserCoupon::getIsDelete, DeleteEnum.NORMAL.getCode()));
            if (CollectionUtils.isNotEmpty(userCoupons)){
                userCoupons.stream().forEach(v->{
                    v.setIsDelete(DeleteEnum.DELETE.getCode());
                    v.setUpdateTime(LocalDateTime.now());
                    v.setUpdateBy(signOutUserDTO.getUserCode());
                    userCouponMapper.update(v);
                });
            }
            UserSettings userSettings = userSettingsMapper.selectOne(Wrappers.<UserSettings>lambdaQuery().eq(UserSettings::getUserId, userInfo.getId()).eq(UserSettings::getIsDelete, DeleteEnum.NORMAL.getCode()));
            if (!Objects.isNull(userSettings)){
                userSettings.setIsDelete(DeleteEnum.DELETE.getCode());
                userSettings.setUpdateBy(signOutUserDTO.getUserCode());
                userSettingsMapper.update(userSettings);
            }
        }
        return Constants.success;
    }

    @Override
    public String updateUserMsg(UpdateUserDTO updateUserDTO){
        UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
                .eq(UserInfo::getUserCode, updateUserDTO.getUserCode())
                .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
        if (Objects.isNull(userInfo)){
            return Constants.user_not_exist;
        }

        UserInfo params = new UserInfo();
        if (StringUtils.isBlank(userInfo.getUserName()) && StringUtils.isNotBlank(updateUserDTO.getUserName())){
            params.setUserName(updateUserDTO.getUserName());
        }
        if (StringUtils.isNotBlank(updateUserDTO.getNickName())){
            UserInfo userInfoExits = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
                    .like(UserInfo::getNickName, updateUserDTO.getNickName())
                    .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
            if (!Objects.isNull(userInfoExits)){
                return Constants.nick_name_exist;
            }
            params.setNickName(updateUserDTO.getNickName());
        }
        if (StringUtils.isNotBlank(updateUserDTO.getIdCard())){
            params.setIdCard(updateUserDTO.getIdCard());
            Map<String, String> carInfo = idCardUtil.getCarInfo(updateUserDTO.getIdCard());
            params.setBirthday(carInfo.get("birthday"));
            params.setGender(Integer.valueOf(carInfo.get("gender")));
            params.setIdCardAddress(carInfo.get("address"));
        }else{
            params.setGender(updateUserDTO.getGender());
        }
        params.setMobile(updateUserDTO.getMobile());
        params.setFamilyAddress(updateUserDTO.getFamilyAddress());
        params.setCompanyAddress(updateUserDTO.getCompanyAddress());
        userInfoDao.update(params);

        UserSettings userSettings = userSettingsMapper.selectOne(Wrappers.<UserSettings>lambdaQuery().eq(UserSettings::getUserCode,updateUserDTO.getUserCode()));
        if (Objects.isNull(userSettings)){
            UserSettings userSettingsParams = new UserSettings();
            userSettingsParams.setUserId(userInfo.getId());
            userSettingsParams.setUserCode(updateUserDTO.getUserCode());
            userSettingsParams.setMobile(updateUserDTO.getMobile());
            userSettingsParams.setWeChat(updateUserDTO.getWeChat());
            userSettingsParams.setEmail(updateUserDTO.getEmail());
            userSettingsParams.setQq(updateUserDTO.getQq());
            userSettingsParams.setLabel(updateUserDTO.getLabel());
            userSettingsParams.setIsDelete(DeleteEnum.NORMAL.getCode());
            userSettingsParams.setCreateBy(userInfo.getUserCode());
            userSettingsParams.setUpdateBy(userInfo.getUserCode());
            userSettingsParams.setCreateTime(LocalDateTime.now());
            userSettingsParams.setUpdateTime(LocalDateTime.now());
            userSettingsMapper.insert(userSettingsParams);
        }else{
            UserSettings userSettingsParams = new UserSettings();
            userSettingsParams.setMobile(updateUserDTO.getMobile());
            userSettingsParams.setWeChat(updateUserDTO.getWeChat());
            userSettingsParams.setEmail(updateUserDTO.getEmail());
            userSettingsParams.setQq(updateUserDTO.getQq());
            userSettingsParams.setLabel(updateUserDTO.getLabel());
            userSettingsParams.setUpdateBy(userInfo.getUserCode());
            userSettingsParams.setUpdateTime(LocalDateTime.now());
            userSettingsMapper.update(userSettingsParams);
        }
        return Constants.success;
    }

    @Override
    public UserDetailsDTO findUserDetailsCode(String userCode){
        UserDetailsDTO result = new UserDetailsDTO();
        UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getUserCode, userCode).eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
        UserSettings userSettings = userSettingsMapper.selectOne(Wrappers.<UserSettings>lambdaQuery().eq(UserSettings::getUserCode, userCode).eq(UserSettings::getIsDelete, DeleteEnum.NORMAL.getCode()));
        List<UserCoupon> userCoupons = userCouponMapper.selectList(Wrappers.<UserCoupon>lambdaQuery().eq(UserCoupon::getUserCode, userCode).eq(UserCoupon::getIsDelete, DeleteEnum.NORMAL.getCode()));
        userInfo.setPassword(null);
        userInfo.setPayPassword(null);
        result.setUserInfo(userInfo);
        result.setUserSettings(userSettings);
        result.setCouponList(userCoupons);
        return result;
    }

    @Override
    public String login(UserLoginDTO userLoginDTO){
        UserInfo userInfo;
        Integer loginType = userLoginDTO.getLoginType();
        if (LoginTypeEnum.USER_NAME_AND_PASSWORD.getCode().equals(loginType)){

        }
        return Constants.success;
    }

    public Map<String,Object> findUserNameAndPassword(String userName,String password){
        Map<String,Object> map = new HashMap<>(16);
       UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
               .eq(UserInfo::getUserName, userName)
               .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
       if (Objects.isNull(userInfo)){
           map.put("code","201");
           map.put("message",Constants.user_not_exist);
           return map;
       }
       return map;
    }

    private String mobileRegister(UserRegisterDTO userRegister){
        UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
                .eq(UserInfo::getMobile, userRegister.getMobile())
                .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));

        if (!Objects.isNull(userInfo)){
            return Constants.mobile_exist;
        }
        String phone = userRegister.getMobile();
        String unique = StringCustomizedUtils.generatorUniqueCodeByType(UniqueCodeEnum.USER.getMsg());
        UserInfo param = new UserInfo();
        param.setPassword(userRegister.getPassword());
        param.setUserCode(unique);
        param.setMobile(phone);
        param.setUserStatus(UserStatusEnum.NORMAL.getCode());
        param.setRegisterType(RegisterTypeEnum.NAME.getCode());
        param.setChannelDrainage(ChannelDrainageEnum.rabbit.getCode());
        param.setIsDelete(DeleteEnum.NORMAL.getCode());
        param.setCreateBy(unique);
        param.setUpdateBy(unique);
        LocalDateTime now = LocalDateTime.now();
        param.setCreateTime(now);
        param.setUpdateTime(now);
        int insert = userInfoDao.insert(param);
        return Constants.success;
    }

    public String nickNameRegister(UserRegisterDTO userRegister) {
        UserInfo userInfo = userInfoDao.selectOne(Wrappers.<UserInfo>lambdaQuery()
                .eq(UserInfo::getNickName,userRegister.getNickName())
                .eq(UserInfo::getIsDelete, DeleteEnum.NORMAL.getCode()));
        if (!Objects.isNull(userInfo)){
            return Constants.nick_name_exist;
        }
        String nickname = userRegister.getNickName();

        UserInfo param = new UserInfo();
        String unique = StringCustomizedUtils.generatorUniqueCodeByType(UniqueCodeEnum.USER.getMsg());
        param.setPassword(userRegister.getPassword());
        param.setUserCode(unique);
        param.setNickName(nickname);
        param.setUserStatus(UserStatusEnum.NORMAL.getCode());
        param.setRegisterType(RegisterTypeEnum.NAME.getCode());
        param.setChannelDrainage(ChannelDrainageEnum.rabbit.getCode());
        param.setIsDelete(DeleteEnum.NORMAL.getCode());
        param.setCreateBy(unique);
        param.setUpdateBy(unique);
        LocalDateTime now = LocalDateTime.now();
        param.setCreateTime(now);
        param.setUpdateTime(now);
        int insert = userInfoDao.insert(param);
        return Constants.success;
    }
}
